package com.campus.statisticaltool;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * @ClassName: StatisticalTool
 * @Description: 代码统计工具小程序
 * @Author: hp
 * @Date: 2021/7/20 17:24
 * @version: 1.0
 */
public class StatisticalTool {

    /**
     * 读取文件失败返回码
     */
    private static final String EXIT = "exit";

    private static final String SINGLE_NOTE = "//";

    private static final String DOUBLE_NOTE_START = "/*";

    private static final String DOUBLE_NOTE_END = "*/";

    /**
     * 本周编程题目：使用熟悉的语言实现一个代码统计工具小程序。
     * 实现的基本功能:
     * 控制台输入文件路径、待统计的字符；
     * 输出文件中的行数、注释行数、待统计字符出现位置及次数
     * 可根据自己的想法拓展其他功能。
     * <p>
     * 备注：去年编程大赛的比赛要求，
     * 1.功能完整
     * 2.代码整洁
     * 3.测试保障
     * 4.小步提交）
     *
     * @param args 参数
     */
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String begin = "";

        while (!begin.equals(EXIT)) {
            System.out.println("请输入待统计的文件路径：");
            // E:\IDEA\CampusProject\src\main\java\com\campus\calculator\Calculator.java
            String filePath = sc.next();
            System.out.println("请输入待统计字符：");
            String readyString = sc.next();

            try {
                System.out.println("文件总行数：" + totalLineNum(filePath));
                System.out.println("文件注释行数：" + noteLineNum(filePath));

                List stringLocation = getStringLocation(filePath, readyString);
                System.out.println("匹配字符数量：" + stringLocation.size());
                System.out.println("匹配字符位置如下：");
                System.out.println(stringLocation.toString());
            } catch (IOException e) {
                System.out.println("-------------------------------------------------");
                System.out.println("\t\t\t\t读取文件异常");
                System.out.println("-------------------------------------------------");
            }

            System.out.print("\n任意输入继续，输入 exit 退出：");
            begin = sc.next();
            System.out.println();
        }
    }

    /**
     * 获取匹配字符的位置信息
     *
     * @param filePath    文件路径
     * @param readyString 待匹配字符
     * @return 匹配字符的位置列表
     */
    private static List<String> getStringLocation(String filePath, String readyString) throws IOException {
        List<String> stringLocation = new ArrayList<String>();

        File file = new File(filePath);
        int lineNum = 0;

        BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
        String enumLine;
        while ((enumLine = bufferedReader.readLine()) != null) {
            enumLine = enumLine.trim();
            lineNum++;
            int readyStringIndex = 0;
            if (enumLine.contains(readyString)) {
                while (readyStringIndex != -1) {
                    readyStringIndex = enumLine.indexOf(readyString, readyStringIndex + readyString.length());
                    if (readyStringIndex != -1) {
                        stringLocation.add(lineNum + "行" + (readyStringIndex + 1) + "个");
                    }
                }
            }
        }
        bufferedReader.close();

        return stringLocation;
    }

    /**
     * 总行数统计
     *
     * @param filePath 文件
     * @return 文件内容行数
     */
    private static int totalLineNum(String filePath) throws IOException {
        int totalLine = 0;

        File file = new File(filePath);

        BufferedReader br;
        br = new BufferedReader(new FileReader(file));
        while (br.readLine() != null) {
            totalLine++;
        }
        br.close();

        return totalLine;
    }

    /**
     * 注释行数统计
     *
     * @param filePath 文件
     * @return 文件注释内容行数
     */
    private static int noteLineNum(String filePath) throws IOException {
        int noteLine = 0;

        File file = new File(filePath);

        BufferedReader br;
        br = new BufferedReader(new FileReader(file));
        String enumLine;
        while ((enumLine = br.readLine()) != null) {
            enumLine = enumLine.trim();
            if (enumLine.startsWith(SINGLE_NOTE)) {
                noteLine++;
            } else if (enumLine.startsWith(DOUBLE_NOTE_START)) {
                if (enumLine.endsWith(DOUBLE_NOTE_END)) {
                    noteLine++;
                } else {
                    noteLine++;
                    while (!enumLine.endsWith(DOUBLE_NOTE_END)) {
                        noteLine++;
                        enumLine = br.readLine().trim();
                    }
                }
            }
        }
        br.close();

        return noteLine;
    }

}
